<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			body{
				background-color: #000;
			}
			#myCanvas{
				display: block;
				margin: 40px auto;
				border: 1px solid #f40;
			}
		</style>
	</head>
	<body>
		<canvas id="myCanvas" width="800" height="800"></canvas>
		<script type="text/javascript">
			var canvas = document.querySelector("#myCanvas")
			var cx = canvas.getContext("2d")
			var f = 400
			var dis = 1400
			var rY = 0
			var rX = 0
			var isPress = false
			var dragX = 0
			var dragY = 0
			var _currX = 0
			var _currY = 0
			var grd=cx.createRadialGradient(100,100,2,100,100,50);
			grd.addColorStop(0,"#fff");
			grd.addColorStop(.1,"#ffffff33");
			grd.addColorStop(1,"#ffffff00");
			cx.fillStyle = grd;
			cx.save()
			function Particle(option){
				Object.assign(this,{
					pList: [], // 集中管理粒子
					emitterPos: [400,400], // 发射器坐标
					nPs: 20, // 每秒发射的粒子数量
					timer: null, // 动画计时器
					cTimer: null, // 创建粒子计时器
					tTimer: null, // 计时计时器
					life: 5000 ,// 粒子生命 (ms)
					ms: 0, // 当前时间
					dur: 10 // 发射粒子间隔(需初始化)
				},option)
				this.init()
			}
			Particle.prototype.expend = function(obj){
				Object.assign(this,obj)
			}
			Particle.prototype.expend({
				init(){
					this.dur = Math.floor(1000 / this.nPs) // 初始化粒子发射时间间隔
					this.addEvent()
					this.emit()
					// 点击屏幕锁定画面
					// canvas.onclick = ()=>{
					// 	clearInterval(this.timer)
					// }
				},
				// 添加事件监听器
				addEvent(){
					canvas.onmousedown = function(){
						isPress = true
						_currX = event.pageX + dragX
						_currY = event.pageY / 2 + dragY
					}
					canvas.onmousemove = function(){
						if(isPress){
							dragX = _currX - event.pageX
							dragY = _currY - event.pageY / 2
							rY = dragX * Math.PI / 180
							rX = dragY * Math.PI / 180
						}
					}
					canvas.onmouseup = function () {
						isPress = false
					}
					window.onmousewheel = function(){
						dis += event.deltaY
					}
				},
				// 开始发射
				emit(){
					this.createParticle() // 创建粒子
					this.timer = setInterval(()=>{
						this.ms = performance.now()
						// this.calculate() // 计算位置
						this.draw() // 绘制
					},16)
				},
				// 创建粒子线程
				createParticle(){
					for(var i = 0; i < 20; i++){
						for(var j = 0; j < 20; j++){
							this.pList.push({
								pos: [(i-10) * 40,(j-10) * 40,(Math.random()-.5)*800], // 粒子三维坐标
								size: Math.random() * 10 + 2, // 粒子尺寸
								fillColor: "#ffffff", // 粒子颜色
								age: 0 // 粒子年龄
							})
						}
					}
				},
				// 计算
				calculate(){
					this.pList.forEach(p=>{
						p.age += 16 // 本粒子年龄 (ms)
						p.pos[0] = 200 * Math.sin(p.age / 500 * Math.PI) * (p.age / this.life)
						p.pos[1] = -p.age / 10
						p.pos[2] = 200 * Math.cos(p.age / 500 * Math.PI) * (p.age / this.life)
					})
				},
				// 绘制
				draw(){
					cx.save()
					cx.clearRect(0,0,800,800)
					cx.translate(this.emitterPos[0],this.emitterPos[1])
					this.pList.forEach(p=>{
						cx.save()
						var pos_2d = this.deDiv(p.pos)
						var grd=cx.createRadialGradient(200 * pos_2d.multi,200 * pos_2d.multi,2 * pos_2d.multi,200 * pos_2d.multi,200 * pos_2d.multi,50 * pos_2d.multi);
						var rdm = Math.random()*.5+.5
						grd.addColorStop(0,"rgba(255,255,255,1)");
						grd.addColorStop(.1,"rgba(38, 245, 255,"+rdm*.2+")");
						// grd.addColorStop(.1,"rgba(38, 245, 255, 1.0)");
						grd.addColorStop(1,"rgba(123, 57, 255, 0.0)");
						cx.fillStyle = grd;
						cx.translate(pos_2d.res[0] * pos_2d.multi, pos_2d.res[1] * pos_2d.multi)
						// 方形
						cx.fillRect(0,0,400 * pos_2d.multi, 400 * pos_2d.multi)
						cx.restore()
					})
					cx.restore()
				},
				// 降维
				deDiv(pos_v3){
					var res1 = this.rotateY(...pos_v3,rY)
					var res = this.rotateX(...res1,rX)
					var multi = f / (dis - res[2] - f)
					multi = multi < 0 ? 0 : multi
					return {res,multi}
				},
				rotateY(x,y,z,a){
					// 绕 Y 轴旋转角度 a
					var x1 = x, z1 = z;
					x1 = x * Math.cos(a) - z * Math.sin(a)
					z1 = z * Math.cos(a) + x * Math.sin(a)
					return [x1,y,z1]
				},
				rotateX(x,y,z,a){
					// 绕 X 轴旋转角度 a
					var y1 = y, z1 = z;
					y1 = y * Math.cos(a) - z * Math.sin(a)
					z1 = z * Math.cos(a) + y * Math.sin(a)
					return [x,y1,z1]
				}
			})
			new Particle()
		</script>
	</body>
</html>
